import sys
import random
import time
import pygame

MINE_COUNT = 99
BLOCK_SIZE = 16
ROW_NUM = 16
COLUMN_NUM = 30

SCREEN_WIDTH, SCREEN_HEIGHT = COLUMN_NUM*BLOCK_SIZE, (ROW_NUM+2)*BLOCK_SIZE

def get_game_status(board_list):
    cnt = 0
    for row in range(ROW_NUM):
        for col in range(COLUMN_NUM):
            if board_list[row][col]["tag"] == "boom":
                return "over"
            
            if board_list[row][col]["tag"] == "flag" and board_list[row][col]["mine"]:
                cnt += 1
    
    if cnt == MINE_COUNT:
        return "win"
    else:
        return "normal"

"""
open the block. if the block is blank, then open around it
"""
def open_block(row, col, board_list):
    if board_list[row][col]["opened"]:
        return
    
    mine_num = get_mine_num(row, col, board_list)
    board_list[row][col]["opened"] = True
    board_list[row][col]["tag"] = mine_num

    for i, j in [(-1,-1), (-1,1), (1,-1), (1,1), (-1,0), (1,0), (0,-1), (0,1)]:
        if (0 <= row+i <= (ROW_NUM-1)) and (0 <= col+j <= (COLUMN_NUM-1)):
            if board_list[row+i][col+j]["mine"]:
                continue

            mine_num = get_mine_num(row+i, col+j, board_list)
            if mine_num > 0:
                board_list[row+i][col+j]["opened"] = True
                board_list[row+i][col+j]["tag"] = mine_num
            else:
                open_block(row+i, col+j, board_list)

def get_all_flag_num(board_list):
    num = 0
    for row in range(ROW_NUM):
        for col in range(COLUMN_NUM):
            if board_list[row][col]["tag"] == "flag":
                num += 1
    return num

def open_all_mine(board_list):
    for row in range(ROW_NUM):
        for col in range(COLUMN_NUM):
            if board_list[row][col]["mine"] and board_list[row][col]["opened"] == False:
                board_list[row][col]["opened"] = True
                board_list[row][col]["tag"] = "mine"

"""
get the number of mines around the block
"""
def get_mine_num(row, col, board_list):
    return get_around_num(row, col, board_list, "mine", True)

"""
get the number of flags around the block
"""
def get_flag_num(row, col, board_list):
    return get_around_num(row, col, board_list, "tag", "flag")

"""
get the number of key around the block
"""
def get_around_num(row, col, board_list, key, value):
    num = 0
    for i, j in [(-1,-1), (-1,1), (1,-1), (1,1), (-1,0), (1,0), (0,-1), (0,1)]:
        if (0 <= row+i <= (ROW_NUM-1)) and (0 <= col+j <= (COLUMN_NUM-1)):
            if board_list[row+i][col+j][key] == value:
                num += 1
    return num

"""
"""
def open_around_block(row, col, board_list):
    if not board_list[row][col]["opened"]:
        return

    if board_list[row][col]["tag"] != get_flag_num(row, col, board_list):
        return

    for i, j in [(-1,-1), (-1,1), (1,-1), (1,1), (-1,0), (1,0), (0,-1), (0,1)]:
        if (0 <= row+i <= (ROW_NUM-1)) and (0 <= col+j <= (COLUMN_NUM-1)):
            if board_list[row+i][col+j]["opened"]:
                continue
            
            if board_list[row+i][col+j]["tag"] == "flag":
                continue

            if not board_list[row+i][col+j]["mine"]:
                open_block(row+i, col+j, board_list)
        
            elif board_list[row+i][col+j]["mine"]:
                board_list[row+i][col+j]["opened"] = True
                board_list[row+i][col+j]["tag"] = "boom"


def left_click_block(row, col, board_list):
    if board_list[row][col]["opened"]:
        open_around_block(row, col, board_list)
        return
    
    if not board_list[row][col]["mine"]:
        open_block(row, col, board_list)
        
    elif board_list[row][col]["mine"]:
        board_list[row][col]["opened"] = True
        board_list[row][col]["tag"] = "boom"

def right_click_block(row, col, board_list):
    if board_list[row][col]["opened"]:
        open_around_block(row, col, board_list)
        return

    if board_list[row][col]["tag"] == "unopened":
        board_list[row][col]["tag"] = "flag"
    elif board_list[row][col]["tag"] == "flag":
        board_list[row][col]["tag"] = "ask"
    elif board_list[row][col]["tag"] == "ask":
        board_list[row][col]["tag"] = "unopened"
    

def init_board(row, col):
    nums = [{"opened":False, "mine":False, "tag":"unopened"} for _ in range(row*col - MINE_COUNT)]
    nums += [{"opened":False, "mine":True, "tag":"unopened"} for _ in range(MINE_COUNT)]
    random.shuffle(nums)
    return [list(x) for x in zip(*[iter(nums)]*col)]

"""
get the click block
"""
def get_click_block(x, y):
    for row in range(ROW_NUM):
        for col in range(COLUMN_NUM):
            if col*BLOCK_SIZE <= x <= (col+1)*BLOCK_SIZE and row*BLOCK_SIZE <= y <= (row+1)*BLOCK_SIZE:
                return row, col

def run(screen):
    bgcolor = (255, 255, 255)

    board_list = init_board(ROW_NUM, COLUMN_NUM)
    img_blocks = init_block_imgs()
    img_nums = init_num_imgs()

    # font = pygame.font.Font("", BLOCK_SIZE*2)
    # f_width, f_height = font.size("999")
    red = (200, 40, 40)
    flag_count = 0

    elapsed_time = 0
    last_time = time.time()
    start_record_time = False

    clock = pygame.time.Clock()
    
    game_status = "normal"
    while game_status == "normal":
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            elif event.type == pygame.MOUSEBUTTONDOWN:
                x, y = pygame.mouse.get_pos()
                if 2*BLOCK_SIZE <= y <= SCREEN_HEIGHT:
                    position = get_click_block(x, y-2*BLOCK_SIZE)
                    if event.button == 1:
                        left_click_block(*position, board_list)
                    elif event.button == 3:
                        right_click_block(*position, board_list)

        game_status = get_game_status(board_list)
        if game_status == "win":
            pass
        elif game_status == "over":
            open_all_mine(board_list)

        screen.fill(bgcolor)

        #显示block
        for row in range(ROW_NUM):
            for col in range(COLUMN_NUM):
                screen.blit(img_blocks[board_list[row][col]["tag"]], (col*BLOCK_SIZE, (row+2)*BLOCK_SIZE))

        #显示表情

        #显示剩余雷的数量
        show_surplus_mine(board_list, img_nums, screen)

        #显示耗时
        pygame.display.update()

        clock.tick(60)

def show_surplus_mine(board_list, imgs, screen):
    flags = get_all_flag_num(board_list)
    surplus = MINE_COUNT - flags
    show_num(surplus, 4, 4, imgs, screen)

def show_num(value, x, y, imgs, screen):
    a = value%10  #个位
    b = value//10%10  #十位
    c = value//100  #百位
    screen.blit(imgs[c], (x, y))
    screen.blit(imgs[b], (x+13, y))
    screen.blit(imgs[a], (x+13*2, y))

def main():
    pygame.init()
    pygame.display.set_caption("扫雷")
    screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
    # while True:
    run(screen)
    time.sleep(10)

def cropimg(image, region):
    from PIL import Image
    img = Image.open(image)
    cropImg = img.crop(region)
    print(cropImg.size)
    imgx = pygame.image.frombuffer(cropImg.tobytes(), cropImg.size, "RGBA")
    return imgx

def loadimg(image, row, col, width, height):
    region = (row*width, col*height, (row+1)*width, (col+1)*height)
    img = cropimg(image, region)
    # img = pygame.transform.smoothscale(img, (width, height))
    return img


def init_block_imgs():
    img_unopened = loadimg(r"tile.png", 0, 0, BLOCK_SIZE, BLOCK_SIZE)
    img_blank    = loadimg(r"tile.png", 0, 1, BLOCK_SIZE, BLOCK_SIZE)
    img_flag     = loadimg(r"tile.png", 0, 2, BLOCK_SIZE, BLOCK_SIZE)
    img_ask      = loadimg(r"tile.png", 0, 3, BLOCK_SIZE, BLOCK_SIZE)
    img_ask_open = loadimg(r"tile.png", 0, 4, BLOCK_SIZE, BLOCK_SIZE)
    img_mine     = loadimg(r"tile.png", 0, 5, BLOCK_SIZE, BLOCK_SIZE)
    img_mine_red = loadimg(r"tile.png", 0, 6, BLOCK_SIZE, BLOCK_SIZE)
    img_mine_cross = loadimg(r"tile.png", 0, 7, BLOCK_SIZE, BLOCK_SIZE)
    img_one      = loadimg(r"tile.png", 1, 0, BLOCK_SIZE, BLOCK_SIZE)
    img_two      = loadimg(r"tile.png", 1, 1, BLOCK_SIZE, BLOCK_SIZE)
    img_three    = loadimg(r"tile.png", 1, 2, BLOCK_SIZE, BLOCK_SIZE)
    img_four     = loadimg(r"tile.png", 1, 3, BLOCK_SIZE, BLOCK_SIZE)
    img_five     = loadimg(r"tile.png", 1, 4, BLOCK_SIZE, BLOCK_SIZE)
    img_six      = loadimg(r"tile.png", 1, 5, BLOCK_SIZE, BLOCK_SIZE)
    img_seven    = loadimg(r"tile.png", 1, 6, BLOCK_SIZE, BLOCK_SIZE)
    img_eight    = loadimg(r"tile.png", 1, 7, BLOCK_SIZE, BLOCK_SIZE)
    imgs = {"unopened":img_unopened, 0:img_blank, "flag":img_flag, "ask":img_ask, "mine":img_mine, "boom":img_mine_red, 
            1:img_one, 2:img_two, 3:img_three, 4:img_four, 5:img_five, 6:img_six, 7:img_seven, 8:img_eight}
    return imgs

def init_num_imgs():
    img_zero  = loadimg(r"score.jpg", 0, 0, 13, 23)
    img_one   = loadimg(r"score.bmp", 0, 1, 13, 23)
    img_two   = loadimg(r"score.bmp", 0, 2, 13, 23)
    img_three = loadimg(r"score.bmp", 0, 3, 13, 23)
    img_four  = loadimg(r"score.bmp", 0, 4, 13, 23)
    img_five  = loadimg(r"score.bmp", 0, 5, 13, 23)
    img_six   = loadimg(r"score.bmp", 0, 6, 13, 23)
    img_seven = loadimg(r"score.bmp", 0, 7, 13, 23)
    img_eight = loadimg(r"score.bmp", 0, 8, 13, 23)
    img_nine  = loadimg(r"score.bmp", 0, 9, 13, 23)
    imgs = {0:img_zero, 1:img_one, 2:img_two, 3:img_three, 4:img_four, 5:img_five, 6:img_six, 7:img_seven, 8:img_eight, 9:img_nine}
    return imgs


if __name__ == "__main__":
    main()